import os
import requests
import openpyxl
from django.conf import settings
from django.http import JsonResponse, FileResponse
from django.views.decorators.csrf import csrf_exempt
from pdfplumber import open as pdf_open
from docx import Document
from rest_framework.decorators import api_view


@csrf_exempt
@api_view(["POST"])
def aiCase(request):
    """生成测试用例API，调用前删除已有的 test_cases.xlsx 文件"""
    # 定义要删除的文件路径
    filename = "test_cases.xlsx"
    filepath = os.path.join(settings.MEDIA_ROOT, filename)

    # 检查并删除已存在的文件
    if os.path.exists(filepath):
        try:
            os.remove(filepath)
            print(f"已删除旧文件: {filepath}")
        except Exception as e:
            print(f"删除旧文件失败: {str(e)}")
            # 这里可根据需求决定是否抛出错误，若不影响生成可继续执行
            # return JsonResponse({"error": f"删除旧文件失败: {str(e)}"}, status=500)

    # 创建存储目录（确保目录存在，可不做修改）
    media_path = os.path.join(settings.MEDIA_ROOT)
    os.makedirs(media_path, exist_ok=True)

    # 解析请求数据
    text_input = request.POST.get('text', '')
    files = request.FILES.getlist('files')

    # 合并所有文本内容
    combined_content = text_input + "\n"

    # 解析上传的文件
    for file in files:
        if file.name.endswith('.pdf'):
            try:
                with pdf_open(file) as pdf:
                    for page in pdf.pages:
                        combined_content += page.extract_text() + "\n"
            except Exception as e:
                print(f"PDF解析错误: {e}")
        elif file.name.endswith('.docx'):
            try:
                doc = Document(file)
                for para in doc.paragraphs:
                    combined_content += para.text + "\n"
            except Exception as e:
                print(f"DOCX解析错误: {e}")

    # 调用DeepSeek API
    api_url = settings.DEEPSEEK_API_URL
    api_key = settings.DEEPSEEK_API_KEY
    headers = {
        'Content-Type': 'application/json',
        'Authorization': f'Bearer {api_key}'
    }

    prompt = f"""
    请根据以下需求生成测试用例，严格使用以下表格格式（不要省略任何列）：
    用例编号|功能模块|用例标题|前置条件|操作步骤|测试数据|预期结果|实际结果|通过否|优先级
    要求：
    1. 至少生成50条测试用例，覆盖所有功能模块
    2. 操作步骤需详细到具体交互
    3. 测试数据需包含具体值
    4. 优先级用高/中/低表示
    5. 仅返回表格内容，无任何说明
    6. 表格格式：每行用竖线(|)分隔字段，无额外空格
    7. 实际结果和通过否列留空，其他列不能为空
    需求内容：
    {combined_content}
    """

    data = {
        "model": "DeepSeek-R1",
        "messages": [
            {"role": "system", "content": "你是专业测试工程师，按用户格式生成完整测试用例"},
            {"role": "user", "content": prompt}
        ],
        "temperature": 0.2,
        "max_tokens": 8000
    }

    # 发送请求（关闭流式，确保完整响应）
    try:
        response = requests.post(
            url=api_url,
            headers=headers,
            json=data,
            stream=False,
            verify=False,
            timeout=(600, 1200)  # 连接超时10分钟，读取超时20分钟，单位是秒级
        )
        response.raise_for_status()
        result = response.json()
        ai_response = result['choices'][0]['message']['content']
    except Exception as e:
        return JsonResponse({"error": f"API调用失败: {str(e)}"}, status=500)

    # 解析AI响应并生成Excel
    try:
        wb = openpyxl.Workbook()
        ws = wb.active
        ws.title = "测试用例"
        headers = ["用例编号", "功能模块", "用例标题", "前置条件", "操作步骤", "测试数据", "预期结果", "实际结果",
                   "通过否", "优先级"]
        ws.append(headers)

        lines = ai_response.strip().split('\n')
        test_case_count = 0
        for line in lines:
            if not line.strip() or line.startswith('---'):
                continue  # 跳过空行和分隔线
            # 按竖线分割并处理空字段
            cells = [cell.strip() for cell in line.split('|') if cell.strip() or cell.strip() == '']
            # 补全缺失列（至少10列）
            if len(cells) < len(headers):
                cells.extend([""] * (len(headers) - len(cells)))
            # 截断多余列
            cells = cells[:len(headers)]
            # 写入Excel
            ws.append(cells)
            test_case_count += 1

        filepath = os.path.join(media_path, "test_cases.xlsx")
        wb.save(filepath)
        return JsonResponse({
            "file_url": f"{settings.MEDIA_URL}test_cases.xlsx",
            "message": f"生成成功，共{test_case_count}条用例",
            "count": test_case_count
        })
    except Exception as e:
        return JsonResponse({"error": f"Excel生成失败: {str(e)}"}, status=500)


@api_view(["GET"])
def downloadCase(request):
    """下载测试用例API"""
    try:
        filename = "test_cases.xlsx"
        filepath = os.path.join(settings.MEDIA_ROOT, filename)

        # 检查文件是否存在
        if not os.path.exists(filepath):
            return JsonResponse({"error": "文件不存在，请先生成测试用例"}, status=404)

        # 直接返回文件响应（后端控制文件名）
        response = FileResponse(open(filepath, 'rb'))
        response['Content-Disposition'] = f'attachment; filename="test_case.xlsx"'
        return response

    except Exception as e:
        return JsonResponse({"error": f"下载失败: {str(e)}"}, status=500)
